/**
 * @file rgb3.c
 * @author your name (you@domain.com)
 * @brief BMP文件的每行必须满足 4字节对齐
 * @version 0.1
 * @date 2021-04-28
 * 
 * @copyright Copyright (c) 2021
 * 
 */
#include <stdio.h>
#include <stdint.h>
#include <string.h>

uint32_t rainbowColors[] = {
    0XFF0000, // 红
    0XFFA500, // 橙
    0XFFFF00, // 黄
    0X00FF00, // 绿
    0X007FFF, // 青
    0X0000FF, // 蓝
    0X8B00FF  // 紫
};

typedef struct
{
    uint8_t bfSize; //整个 BMP 文件的大小
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    unsigned int bfOffBits; //偏移数，即位图文件头+位图信息头+调试板大小
} BitmapFileHeader;

typedef struct
{
    uint32_t biSize;
    int biWidth;
    int biHeight;
    uint16_t biPlanes;
    uint16_t biBitCount;
    uint32_t biCompression;
    uint32_t biSizeImage;
    int biXPelsPerMeter;
    int biYPelsPerMeter;
    uint32_t biClrUsed;
    uint32_t biClrImportant;
} BitmapInfoHeader;

void writeRGBToBmp(char *filename, int width, int height);

int main(void)
{
    writeRGBToBmp("rainbow_711x711.bmp", 711, 711);
    return 0;
}

int caculateLineBytes(int width)
{
    return (24 * width + 31) / 32 * 4;
}
void writeRGBToBmp(char *filename, int width, int height)
{
    FILE *bitmapFile = fopen(filename, "wb");
    if (!bitmapFile)
    {
        printf("fopen[%s]\n", strerror(errno));
        return;
    }
    else
    {
        printf("fopen [%s] success \n", filename);
    }
    uint16_t bfType = 0x4d42; //固定头部,转换为字符为 'B' 'M'

    int lineBytes = caculateLineBytes(width);

    BitmapFileHeader fileHeader;
    fileHeader.bfReserved1 = 0;
    fileHeader.bfReserved2 = 0;
    fileHeader.bfSize = sizeof(bfType) + sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + lineBytes * height; //整个BMP文件大小
    fileHeader.bfOffBits = 0x36;                                                                                   //固定 0x36

    BitmapInfoHeader infoHeader;
    infoHeader.biSize = sizeof(BitmapInfoHeader); //文件信息头
    infoHeader.biWidth = width;                   //位图的宽度

    //biHeight 为正，位图自底向顶扫描，biHeight 为负，位图自顶向底扫描。
    infoHeader.biHeight = -height; //位图的高度
    infoHeader.biPlanes = 1;       //固定值1
    infoHeader.biBitCount = 24;    //每个像素的位数 ，可以是1-黑白 4-16色 8-256色 24-真彩色 32 带透明
    infoHeader.biCompression = 0;  //压缩方式，BI_RGB(0)为不压缩
    infoHeader.biSizeImage = 0;    //当biCompression为BI_RGB时，可设置为0

    /* 不清楚这里的 biXPelsPerMeter(水平分辨率)和biYPelsPerMeter(垂直分辨率)的作用和影响 */
    infoHeader.biXPelsPerMeter = 5000;
    infoHeader.biYPelsPerMeter = 5000;
    infoHeader.biClrUsed = 0;
    infoHeader.biClrImportant = 0;

    fwrite(&bfType, sizeof(bfType), 1, bitmapFile);
    fwrite(&fileHeader, sizeof(fileHeader), 1, bitmapFile);
    fwrite(&infoHeader, sizeof(infoHeader), 1, bitmapFile);

    int j = 1;
    for (int i = 0; i < width; i++)
    {
        uint32_t currentColor = rainbowColors[0];

        if (i < j * 100)
        {
            currentColor = rainbowColors[j - 1];
        }
        else
        {
            j++;
            //// 一旦进入else 则 currentColor 不会发生变化，需要取消这次循环对 i 的变化。
            i--;
            continue;
        }

        uint8_t R = (currentColor & 0xFF0000) >> 16;
        uint8_t G = (currentColor & 0x00FF00) >> 8;
        uint8_t B = (currentColor & 0x0000FF) >> 0;

        uint8_t lineBytesArray[lineBytes]; //一行符合四字节对齐的容器 //lineBytes = 2136

        //填充一行数据的内容
        for (int j = 0; j < height; j++)
        {
            int currenIndex = 3 * j;
            lineBytesArray[currenIndex] = B;
            lineBytesArray[currenIndex + 1] = G;
            lineBytesArray[currenIndex + 2] = R;
        }

        fwrite(lineBytesArray, sizeof(lineBytesArray), 1, bitmapFile); //写了一行的数据 //会在第一行的最后补上3个0   //也就是补上了一个像素单位   // 指定的711*711 结果会变成 712*711
    }

    fclose(bitmapFile);
}
